package com.jamiexu.cn.chatwith.socket;

import com.jamiexu.cn.chatwith.Imp.IConnectionListener;
import com.jamiexu.cn.chatwith.Imp.IOPProcessor;
import com.jamiexu.cn.chatwith.Imp.IServerConnection;
import com.jamiexu.cn.chatwith.server.ServerController;

import java.io.IOException;
import java.net.Socket;

public class ServerConnection implements IServerConnection, IOPProcessor {
    private Socket socket;
    private SocketProtocol socketProtocol;
    private IConnectionListener iConnectionListener;
    private boolean status = true;
    private long stempTime;
    private String nickname;

    public ServerConnection(Socket socket, IConnectionListener iConnectionListener) {
        this.socket = socket;
        this.iConnectionListener = iConnectionListener;
        this.socketProtocol = new SocketProtocol(socket);
        processStatus();
        new Thread(this::processOP).start();
        new Thread(this::listenStatus).start();
    }

    @Override
    public void listenStatus() {
        while (status) {
            if (((System.currentTimeMillis() / 1000) - this.stempTime) > 60) {
                ServerController.SOCKET_CLIENTS.remove(this);
                status = false;
                this.iConnectionListener.disConnected(this.nickname);
                try {
                    this.socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void processOP() {
        while (status) {
            try {
                Object[] objects = this.socketProtocol.getBlock();
                if (objects == null)
                    continue;
                String op = objects[0] + "";
                if (op.equals(SocketProtocol.OP_CONNECTION_CLIENT_CONNECT)) {
                    processConnect(objects[1] + "");
                } else if (op.equals(SocketProtocol.OP_CONNECTION_CLIENT_DISCONNECT)) {
                    processDisconnect(objects[1] + "");
                } else if (op.equals(SocketProtocol.OP_CONNECTION_CLIENT_STATUS)) {
                    processStatus();
                } else if (op.equals(SocketProtocol.OP_MESSAGE_CLIENT_SEND)) {
                    processMessage(objects[1] + "", objects[2] + "");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }


    @Override
    public void sendMessage(String sender, String message) {
        try {
            this.socketProtocol.sendData(SocketProtocol.OP_MESSAGE_SERVER_SEND, sender, message);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public Socket getSocket() {
        return socket;
    }

    public void sendMessageToAll(ServerConnection serverConnection, String sender, String message) {
        for (ServerConnection s :
                ServerController.SOCKET_CLIENTS) {
//            if (serverConnection == s)
//                continue;
            s.sendMessage(sender, message);
        }
    }

    @Override
    public void processConnect(String nickname) {
        try {
            this.socketProtocol.sendData(SocketProtocol.OP_CONNECTION_SERVER_CONNECT);
            ServerController.SOCKET_CLIENTS.add(this);
            this.nickname = nickname;
            this.iConnectionListener.connected(nickname);
            sendMessageToAll(this, this.nickname, "[系统消息]: " + nickname + "进入聊天室");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void processDisconnect(String nickname) {
        try {
            this.socketProtocol.sendData(SocketProtocol.OP_CONNECTION_SERVER_DISCONNECT);
            this.iConnectionListener.disConnected(nickname);
            sendMessageToAll(this, this.nickname, "[系统消息]: " + nickname + "退出聊天室");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void processMessage(String sender, String message) {
        this.iConnectionListener.acceptMessage(sender, message);
        sendMessageToAll(this, sender, message);
    }

    @Override
    public void processStatus() {
        this.stempTime = System.currentTimeMillis() / 1000;
    }
}
